home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 03 - 1987 / 03.07 Jul 87 / pop up source / Overview.p next >
Encoding:
Text File  |  1986-12-18  |  13.2 KB  |  421 lines  |  [TEXT/MPS ]

  1. UNIT OverView; 
  2. {Version 1.0 Saturday, July 12, 1986 9:47:53 PM
  3.  by Scott T. Boyd, the MacHax™ Group
  4.  Many thanks to Greg Marriott of SoftWare To Go,
  5.  also a member of the MacHax™ Group}
  6.  
  7. {Version 1.1 Tuesday, December 16, 1986 11:21:16 PM
  8.  
  9. Hatchet history:
  10.   gbm 9/26/86 - Added parameter to NewOverView for windowKind
  11.  gbm 9/26/86 - Added check to see if scroll bar handles are
  12.      nil in OV_Handle_selection, if they are, don't try
  13.      to set 'em
  14.  gbm 10/1/86 -   Finally figured out what Andrew meant about using
  15.  stb             CalcVisRgn to prevent update events when hiding the window.
  16.  gbm 10/31/86 - Changed OV_HandleSelection to only Inval where the OV window was
  17.      if there were no scroll bars involved (i.e. not scrolling a document)
  18. }
  19.  
  20. {--------------------------------------------------------------------------}
  21. INTERFACE
  22.  
  23. {Compiler Switch Settings}
  24. {$R+}
  25. {$OV+}
  26.  
  27. uses   {$LOAD OV.dump  }
  28.    {$U MemTypes.p  }    MemTypes,
  29.    {$U QuickDraw.p }    QuickDraw,
  30.    {$U OsIntf.p    }    OsIntf,
  31.    {$U ToolIntf.p  }    ToolIntf,
  32.    {$U SANE.p  }    SANE;
  33.  
  34. const
  35.  MenuBarHeight   =  20; {Height of menu bar in pixels}
  36.  TitleBarHeight =  18; {Height of window title bar in pixels}
  37.  ScreenMargin =   4; {Width of "safety margin" around edge of screen}
  38.  SBarHeight  =  15; {Height of scroll bar}
  39.  SBarWidth  =  15; {Width of scroll bar}
  40.  
  41. Procedure NewOverView( var OV_pagePict : bitMap; 
  42.         var OV : WindowPtr; 
  43.         viewRect : Rect;
  44.         factor : Real;
  45.         whatKind : Integer);
  46. Procedure UpdateOverView( Procedure drawProc;
  47.         OV_pagePict : bitMap);
  48. Procedure OverViewSelect( where: Point; 
  49.      viewRect : Rect; VAR scrollPosition : Point; 
  50.      VAR OV : WindowPtr; VAR OV_pagePict : bitMap; 
  51.      HScrollBar,VScrollBar : ControlHandle;
  52.      invertSelection: boolean);
  53.  
  54. {--------------------------------------------------------------------------}
  55. IMPLEMENTATION
  56. Procedure NewOverView ( var OV_pagePict : bitMap; 
  57.         var OV : WindowPtr; 
  58.         viewRect : Rect;
  59.         factor : Real;
  60.         whatKind : Integer);
  61. var
  62.  dummyRect : Rect;
  63.  horizontal,      {horiz. pixel size of the OverView window}
  64.  vertical : Extended;  {vert. pixel size of the OverView window}
  65.  sizeOfOff : Size;   {bytes needed for offscreen bitmap}
  66.  offRowBytes : Integer;  {row bytes needed for offscreen bitmap}
  67.  bitRect  : Rect;   {size of OV window and offscreen bitmap}
  68.  dummy  : Point;
  69.  offPort,      {temporary working port}
  70.  oldPort  : GrafPtr;  {temporary storage}
  71. begin
  72.  {compute available vertical screen space}
  73.  vertical := ScreenBits.bounds.bottom-ScreenBits.bounds.top-MenuBarHeight;
  74.  vertical := vertical * factor;
  75.  
  76.  {compute horizontal to proportion}
  77.  horizontal := vertical * viewRect.right / viewRect.bottom;
  78.  
  79.  {create the new window record}
  80.  SetRect(dummyRect,0,0,Num2Integer(horizontal),Num2Integer(vertical));
  81.  OV := NewWindow( nil,dummyRect,'',FALSE,whatKind,WindowPtr(-1),
  82.      FALSE,LongInt(0) );
  83.  
  84.  {create offscreen bitmap}
  85.  bitRect := OV^.portRect;
  86.  offRowBytes := ((bitRect.right-bitRect.left) div 8) + 1;
  87.  if Odd( offRowBytes ) then offRowBytes := offRowBytes - 1;
  88.  sizeOfOff := (bitRect.bottom-bitRect.top) * offRowBytes;
  89.  with OV_pagePict do
  90.   begin
  91.    baseAddr := QDPtr( NewPtr( sizeOfOff ));
  92.    rowBytes := offRowBytes;
  93.    bounds   := bitRect;
  94.   end;
  95.  
  96.  {fill the bitmap with white}
  97.  GetPort( oldPort );    
  98.  offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  99.  OpenPort( offPort );
  100.  SetPortBits( OV_pagePict );
  101.  FillRect( bitRect, white );
  102.  SetPort( oldPort );
  103.  ClosePort( offPort );
  104.  DisposPtr( Ptr( offPort ));
  105. end; {MakeOverView}
  106.  
  107. {--------------------------------------------------------------------------}
  108. Procedure UpdateOverView( Procedure drawProc;
  109.         OV_pagePict : bitMap);
  110. var
  111.  offPort,
  112.  oldPort  : GrafPtr;
  113. begin
  114.  GetPort( oldPort );
  115.  offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  116.  OpenPort( offPort );
  117.  SetPortBits( OV_pagePict );  {make all drawing happen offscreen}
  118.  
  119.  drawProc;      {let the user draw}
  120.  
  121.  SetPort( oldPort );    {return drawing to normal}
  122.  ClosePort( offPort );
  123.  DisposPtr( Ptr( offPort ));
  124. end; {UpdateOverView}
  125.  
  126. {--------------------------------------------------------------------------}
  127. Procedure OverViewSelect( where: Point; 
  128.      viewRect : Rect; VAR scrollPosition : Point; 
  129.      VAR OV : WindowPtr; VAR OV_pagePict : bitMap; 
  130.      HScrollBar,VScrollBar : ControlHandle;
  131.      invertSelection: boolean);
  132. var
  133.  MenuFlash  : ^Integer;  {system global}
  134.  
  135.  value,       {value returned by TrackGrayRgn}
  136.  h, v   : LongInt;  {}
  137.  
  138.  pane,       {}
  139.  tempPt   : Point;  {}
  140.  
  141.  scope,       {size of window pane scaled into OV window}
  142.  tempRect,
  143.  limitRect,      {limit for drag region}
  144.  slopRect,      {slopiness allowance for dragging}
  145.  structRect  : Rect;   {rect for structure region of ov window}
  146.  
  147.  dragRectRgn  : RgnHandle; {the region the user drags around}
  148.  oldPort   : GrafPtr;
  149.  theWindow  : WindowPtr; {holds the value of frontWindow}
  150.  underScope  : BitMap;  {dynamically allocated offscreen bitmap}
  151.  whichWindow  : WindowPtr; {for save and restore bits}
  152.  clobberedRgn,
  153.  visIntersectRgn : RgnHandle;
  154.  {----------------------------------}
  155.  Procedure OV_Prepare;
  156.  begin
  157.   MenuFlash := pointer($A24);
  158.  
  159.   GetPort( oldPort );
  160.   theWindow := FrontWindow; {theWindow refers to the active window on entry}
  161.   BringToFront( OV );   {make OV appear, but not really}
  162.   SetPort( OV );    {it's now the current port}
  163.   ShowHide( OV, FALSE );  {it's also not visible}
  164.   MoveWindow( OV,0,0,FALSE ); {home the window}
  165.  
  166.   {compute the size of the current window pane}
  167.   pane.h := theWindow^.portRect.right - theWindow^.portRect.left - sBarWidth;
  168.   pane.v := theWindow^.portRect.bottom - theWindow^.portRect.top - sBarHeight;
  169.  
  170.   {scale the pane into the OV window to show size relative to document}
  171.   SetRect( tempRect, 0, 0, pane.h, pane.v );
  172.   MapRect( tempRect, viewRect, OV^.portRect );
  173.   scope := tempRect;
  174.  
  175.   {make the region to drag around.  same size as scope}  
  176.   dragRectRgn := NewRgn;
  177.   RectRgn( dragRectRgn,scope );
  178.   
  179.   {believe it or not, this works to limit the movement of dragRectRgn}
  180.   SetRect( limitRect, 0, 0, OV^.portRect.right-scope.right+1,
  181.           OV^.portRect.bottom-scope.bottom+1 );
  182.  
  183.   {scale scrollPosition into OV for placing scope in OV}
  184.   tempPt := scrollPosition;
  185.   MapPt( tempPt, viewRect, OV^.portRect );
  186.   OffSetRect( scope, tempPt.h, tempPt.v );
  187.  
  188.  end; {OV_Prepare}
  189.  {----------------------------------}
  190.  Procedure OV_PositionOverView;
  191.  var offset : Point;
  192.  begin
  193.   SetPort( oldPort );
  194.   
  195.   tempPt := scrollPosition;
  196.   MapPt( tempPt, viewRect, OV^.portRect );
  197.  
  198.   offset := where;
  199.   
  200.   offset.h := offset.h - tempPt.h;
  201.   offset.v := offset.v - tempPt.v;
  202.   GlobalToLocal ( offset );
  203.   h := offset.h;  {this is the local value of the point of mousedown}
  204.   v := offset.v;
  205.   
  206.   {make sure it doesn't go off current bitmap}
  207.   if (v + OV^.portRect.bottom) >= thePort^.portBits.bounds.bottom
  208.    then v := thePort^.portBits.bounds.bottom - OV^.portRect.bottom - 1;
  209.   {make sure it doesn't go off the right of the window}
  210.   if (h + OV^.portRect.right) >= thePort^.portBits.bounds.right
  211.    then h := thePort^.portBits.bounds.right - OV^.portRect.right - 1;
  212.   {make sure it doesn't go off the top of the window}
  213.   if v < thePort^.portBits.bounds.top then v := thePort^.portBits.bounds.top;
  214.   {make sure it doesn't go off the left of the window}
  215.   if h < thePort^.portBits.bounds.left then h := thePort^.portBits.bounds.left;
  216.   
  217.   SetPt ( offset, h, v);
  218.   LocalToGlobal( offset );
  219.   h := offset.h;
  220.   v := offset.v;
  221.   
  222.   SetPort( OV );
  223.   MoveWindow( OV, h, v, FALSE );
  224.  end; {OV_PositionOverView}
  225.  {----------------------------------}
  226.  procedure OV_SaveBits;
  227.  var
  228.   sizeOfOff : Size;
  229.   offRowBytes : Integer;
  230.   underRect,
  231.   bitRect  : Rect;
  232.   dummy  : Point;
  233.   offPort,
  234.   oldPort  : GrafPtr;
  235.  begin
  236.   GetPort( oldPort );
  237.  
  238.   {put the window magager port into offport as a windowptr}
  239.   GetWMgrPort( offPort );
  240.   whichWindow := WindowPtr( offPort );
  241.  
  242.   {allocate a new grafport}
  243.   offPort := GrafPtr( NewPtr( sizeof( GrafPort )));
  244.   
  245.   {home a copy of the bounds of the OV window}
  246.   bitRect := OV^.portBits.bounds;
  247.   offsetRect( bitRect, -bitrect.left, -bitrect.top );
  248.  
  249.   {compute memory necessary for offscreen bitmap}
  250.   {allocate it and setup bitmap record}
  251.   offRowBytes := ( bitRect.right div 8 ) + 1;
  252.   if Odd( offRowBytes ) then offRowBytes := offRowBytes -1;
  253.   sizeOfOff := bitRect.bottom * offRowBytes;
  254.   with underScope do
  255.   begin
  256.    baseAddr := QDPtr( NewPtr( sizeOfOff ));
  257.    rowbytes := offRowBytes;
  258.    bounds   := bitRect; {using HOMEd rectangle}
  259.   end;
  260.  
  261.   {move a copy (to ensure no scaling occurs) back where OV will appear}
  262.   underRect := underScope.bounds;
  263.   OffsetRect( underRect, h-1, v-1 ); 
  264.  
  265.   {actually save the bits}
  266.   OpenPort( offPort );
  267.   SetPortBits( underScope );
  268.   SetClip( offPort^.visRgn );
  269.   CopyBits( whichWindow^.portBits, underScope,
  270.       underRect, underScope.bounds,
  271.       srcCopy, NIL);
  272.   SetPort( oldPort );
  273.   ClosePort( offPort );
  274.   DisposPtr( Ptr( offPort )); 
  275.  end; {OV_SaveBits}
  276.  {----------------------------------}
  277.  Procedure OV_ShowOverView;
  278.  var
  279.   boxWidth, 
  280.   boxHeight: integer;
  281.   ovSteps, ovMiddle: integer;
  282.   looper : integer;
  283.   thePenState : PenState;
  284.   dummyTicks : longint;
  285.   ovRect : rect;
  286.   oldPort, wPort : GrafPtr;
  287.   oldClip : RgnHandle;
  288.   
  289.  begin 
  290.   OV_SaveBits;
  291.   
  292.   ShowHide( OV, TRUE );  {now the window appears}
  293.   
  294.   {blast miniature picture into OV}
  295.   CopyBits(OV_pagePict,    OV^.portBits, 
  296.      OV_pagePict.bounds, OV^.portRect,
  297.      srcCopy,nil);
  298.   
  299.   {highlight the current selection}
  300.   if invertSelection then InvertRect( scope );
  301.   
  302.   {give the user some room to be sloppy}
  303.   slopRect := OV^.portRect;
  304.   InsetRect( slopRect, -25, -25 );
  305.  
  306.   GlobalToLocal( where );
  307.  
  308.   {compute size of the draggable region and center it on the cursor}
  309.   boxWidth := scope.right - scope.left;
  310.   boxHeight := scope.bottom - scope.top;
  311.   OffsetRgn( dragRectRgn, where.h-(boxWidth div 2), 
  312.         where.v-(boxHeight div 2) );
  313.   OffSetRect( limitRect, boxWidth div 2, boxHeight div 2); 
  314.  
  315.   {let the user drag it around}
  316.   value := DragGrayRgn( dragRectRgn,where,limitRect,slopRect,0,nil );
  317.   
  318.  end; {OV_ShowOverView}
  319.  {----------------------------------}
  320.  Procedure OV_RestoreBits;
  321.  var underRect: Rect;
  322.  begin
  323.    underRect := underScope.bounds;
  324.  
  325.   {home the rectangle}
  326.    OffsetRect( underRect, -underRect.left, -underRect.top);
  327.   
  328.   {position it correctly}
  329.    OffSetRect( underRect, h-1, v-1);
  330.  
  331.   CopyBits( underScope, whichWindow^.portBits, 
  332.       underScope.bounds, underRect,
  333.       srcCopy, NIL);
  334.   {deallocate the bitmap space (be nice and clean)}
  335.   DisposPtr( Ptr( underScope.baseAddr ));
  336.  end; {OV_RestoreBits}
  337.  {----------------------------------}
  338.  Procedure OV_HandleSelection;
  339.   {------------------------}
  340.   Procedure OV_FlashSelection;
  341.   var i: Integer;
  342.    j: LongInt;
  343.   begin
  344.    HLock( Handle( dragRectRgn ));  {try to make this a habit!}
  345.    for i := 1 to 2*MenuFlash^ do begin
  346.     InvertRect( dragRectRgn^^.rgnBBox );
  347.     delay( 4,j );
  348.    end;
  349.    HUnLock( Handle( dragRectRgn )); {but don't forget this part}
  350.   end;
  351.   {------------------------}
  352.  begin {OV_HandleSelection}
  353.   if (HiWord(value)<>-32768) or (LoWord(value)<>-32768)
  354.   then       {user actually made a selection}
  355.    begin
  356.     if invertSelection then
  357.     begin
  358.       InvertRect( scope ); {turn off current selection}
  359.       OV_FlashSelection;
  360.     end;
  361.  
  362.     {hide the window}
  363.     WindowPeek(OV)^.visible := false;  {make it invisible}
  364.     visIntersectRgn:=NewRgn;
  365.     RectRgn(visIntersectRgn,windowPeek(OV)^.strucRgn^^.rgnBBox); {where is OV}
  366.     SetEmptyRgn(WindowPeek(OV)^.strucRgn); {empty his regions...}
  367.     SetEmptyRgn(WindowPeek(OV)^.contRgn);
  368.     SetEmptyRgn(OV^.visRgn);    
  369.     CalcVisBehind( WindowPeek(theWindow),visIntersectRgn); {intersected with old OV}
  370.     DisposeRgn(visIntersectRgn);
  371.  
  372.     SetPort( oldPort );
  373.     OV_RestoreBits;   {blast bits back into place}
  374.  
  375.     {figure the new scrollPosition based on the top-left corner}
  376.     {of the draggable region}
  377.     SetPt( tempPt, dragRectRgn^^.rgnBBox.left, dragRectRgn^^.rgnBBox.top );
  378.     MapPt( tempPt, OV^.portRect, viewRect );
  379.     scrollPosition := tempPt;
  380.     
  381.     tempRect := viewRect;
  382.     tempRect.bottom := tempRect.bottom - pane.v;
  383.     tempRect.right := tempRect.right - pane.h;
  384.     MapPt ( tempPt, tempRect, viewRect );
  385.     
  386.     {set the new scroll bar values}
  387.     if HScrollBar <> nil then SetCtlValue( HScrollBar, tempPt.h );
  388.     if VScrollBar <> nil then SetCtlValue( VScrollBar, tempPt.v );
  389.     if (VScrollBar <> nil) or (HScrollBar<> nil) then InvalRect( theWindow^.portRect );
  390.    end
  391.   else   {no selection was made}
  392.    begin
  393.     {hide the window and make it quick!}
  394.     WindowPeek(OV)^.visible := false;  {make it invisible}
  395.     visIntersectRgn:=NewRgn;
  396.     RectRgn(visIntersectRgn,windowPeek(OV)^.strucRgn^^.rgnBBox); {where is OV}
  397.     SetEmptyRgn(WindowPeek(OV)^.strucRgn); {empty his regions...}
  398.     SetEmptyRgn(WindowPeek(OV)^.contRgn);
  399.     SetEmptyRgn(OV^.visRgn);    
  400.     CalcVisBehind( WindowPeek(theWindow),visIntersectRgn); {intersected with old OV}
  401.     DisposeRgn(visIntersectRgn);
  402.  
  403.     SetPort( oldPort );
  404.     OV_RestoreBits;    {replace the underneath bits}
  405.    end;
  406.  end; {OV_HandleSelection}
  407.  {----------------------------------}
  408.  Procedure OV_TidyUp;
  409.  begin
  410.   DisposeRgn( dragRectRgn );
  411.  end; {OV_TidyUp}
  412.  {----------------------------------}
  413. begin
  414.  OV_Prepare;
  415.  OV_PositionOverView;
  416.  OV_ShowOverView;
  417.  OV_HandleSelection;
  418.  OV_TidyUp;
  419. end; {OverViewSelect}
  420.  
  421. END. {UNIT OverView}